package com.yfqy.app.service;

import com.fasterxml.jackson.core.type.TypeReference;
import com.yfqy.app.security.login.LoginUserInfo;
import com.yfqy.app.util.JSON;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.JwtException;
import io.jsonwebtoken.JwtParser;
import io.jsonwebtoken.Jwts;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @Author: 梁二东
 * @Date: 2025/5/6 17:48
 * @Description:
 **/
@Service
public class JwtService implements InitializingBean {

    private static final Logger logger = LoggerFactory.getLogger(JwtService.class);

    public PrivateKey privateKey;
    public JwtParser jwtParser;

    @Value("${login.jwt.private-key}")
    public String privateKeyBase64;

    @Value("${login.jwt.public-key}")
    public String publicKeyBase64;

    public String createJwt(LoginUserInfo jwtPayload, long expiredAt) {
        //添加构成JWT的参数
        Map<String, Object> headMap = new HashMap<>();
        headMap.put("typ", "JWT");
        Map<String, Object> body = JSON.parse(JSON.stringify(jwtPayload), new TypeReference<Map<String, Object>>() {
        });
        return Jwts.builder()
                .header().add(headMap).and()
                .claims(body)
                .expiration(new Date(expiredAt))
                .signWith(privateKey, Jwts.SIG.RS256)  // 显式指定算法
                .compact();
    }

    private PrivateKey getPrivateKey() {
        try {
            byte[] keyBytes = Base64.getDecoder().decode(privateKeyBase64);
            PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
            return KeyFactory.getInstance("RSA").generatePrivate(spec);
        } catch (Exception e) {
            logger.error("获取Jwt私钥失败", e);
            throw new RuntimeException("获取Jwt私钥失败", e);
        }
    }

    private JwtParser buildJwtParser() {
        try {
            byte[] keyBytes = Base64.getDecoder().decode(publicKeyBase64);
            X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
            PublicKey publicKey = KeyFactory.getInstance("RSA").generatePublic(spec);
            return Jwts.parser()
                    .verifyWith(publicKey)
                    .build();
        } catch (Exception e) {
            throw new RuntimeException("获取Jwt公钥失败", e);
        }
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        privateKey = getPrivateKey();
        jwtParser = buildJwtParser();
    }


    public <T> T verifyJwt(String jwt, Class<T> jwtPayloadClass) {
        if (jwt == null || jwt.isEmpty()) {
            return null;
        }
        try {
            Jws<Claims> jws = jwtParser.parseSignedClaims(jwt);  // 新版方法名
            return JSON.convert(jws.getPayload(), jwtPayloadClass);  // 使用 jjwt 内置转换
        } catch (JwtException e) {
            logger.warn("JWT验证失败: {}", e.getMessage());
            throw e;
        }
    }

    public static <T> T getPayload(String jwt, Class<T> jwtPayloadClass) {
        if (jwt == null || jwt.isEmpty()) {
            return null;
        }
        try {
            // jwt字符串由3部分组成，用英文的点分割：herder.payload.sign
            // 可以直接取中间一段，进行Base64解码
            byte[] decodedBytes = Base64.getDecoder().decode(jwt.split("\\.")[1]);
            return JSON.parse(new String(decodedBytes), jwtPayloadClass);
        } catch (Exception e) {
            return null;
        }
    }

}
